package com.example.security.handler;

import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.example.core.constant.Constant;
import com.example.core.utils.SpringBeanUtils;
import com.example.core.utils.StringUtils;
import com.example.core.utils.UserUtils;
import com.example.sys.auth.constant.AuthConstant;
import com.example.sys.auth.service.SysAuthService;
import com.example.sys.module.po.SysModule;
import com.example.sys.module.service.SysModuleService;
import com.example.sys.org.service.SysElementService;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.schema.Column;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;


/****
 *
 * 数据插件权限过滤
 */
@Service
public class SysDataPermissionHandler implements DataPermissionHandler {

    Logger logger = LoggerFactory.getLogger(getClass());

    public static final String SELECT_PAGE = Constant.POINT + "selectPage";

    private SysModuleService sysModuleService;

    private SysElementService sysElementService;

    private SysAuthService sysAuthService;

    public SysModuleService getSysModuleService() {
        if (sysModuleService == null) {
            sysModuleService = SpringBeanUtils.getApplicationContext().getBean(SysModuleService.class);
        }
        return sysModuleService;
    }

    public SysElementService getSysElementService() {
        if (sysElementService == null) {
            sysElementService = SpringBeanUtils.getApplicationContext().getBean(SysElementService.class);
        }
        return sysElementService;
    }

    public SysAuthService getSysAuthService() {
        if (sysAuthService == null) {
            sysAuthService = SpringBeanUtils.getApplicationContext().getBean(SysAuthService.class);
        }
        return sysAuthService;
    }

    /****
     *
     * 自动拼装SQL并自动拦截SQL
     * @param where
     * @param mappedStatementId
     * @return
     */
    @Override
    public Expression getSqlSegment(Expression where, String mappedStatementId) {
        Expression expression = null;
        if (!StringUtils.isEmpty(mappedStatementId) && mappedStatementId.endsWith(SELECT_PAGE)) {
            String daoClassName = mappedStatementId.replace(SELECT_PAGE, Constant.SPACE);
            SysModule sysModule = getSysModuleService().getModuleByDao(daoClassName);
            if (sysModule != null) {
                if (!UserUtils.hasRole(sysModule.getViewRole())) {
                    if (sysModule.isAuth()) {
                        expression = new EqualsTo();
                        ((EqualsTo) expression).setLeftExpression(new Column(Constant.AUTH_READER_FLAG));
                        ((EqualsTo) expression).setRightExpression(new LongValue(1));
                    }
                    List<String> idLIst = getSysAuthService().findList(AuthConstant.READER, sysModule.getPo(), getSysElementService().getUserAuthIdList());
                    if (!idLIst.isEmpty()) {
                        ItemsList itemsList = new ExpressionList(idLIst.stream().map(LongValue::new).collect(Collectors.toList()));
                        InExpression inExpression = new InExpression(new Column(Constant.ID), itemsList);
                        if (expression == null) {
                            expression = inExpression;
                        } else {
                            expression = new OrExpression(expression, inExpression);
                        }
                    }
                    if (expression == null) {
                        expression = where;
                    } else {
                        if (where != null) {
                            expression = new AndExpression(where, expression);
                        }
                    }
                    return expression;
                }
            }
        }
        return where;
    }

}
